$import( "SmitearWebGL.Objects.Entity" );

SmitearWebGL.Objects.Light = SmitearWebGL.Objects.Entity.extend(
{
	/* * * * * * * * constructor * * * * * * * */

	init : function()
	{
		this._super();
		this._registClass( "SmitearWebGL.Objects.Light" );
		
		/* * * * * * * * public property * * * * * * * */

		this.type = SmitearWebGL.Objects.Light.L_POINT;
		this.baseColor = null;
		this.intensity = 0.8;
		this.constantAttenuation = 1.0;
		this.linearAttenuation = 0.002;
		this.quadraticAttenuation = 0.0008;
		this.spotExponent = 4.0;

		/* * * * * * * * private property * * * * * * * */
		this._displayType = SmitearWebGL.Objects.Entity.DisplayType.LIGHT;
		this._outerCone = 0.6129;
		this._innerCone = 0.7524;
		this._spotPMatrix = null;

		this._direction = null;
		this._worldDir = null;
	}
	,

	/* * * * * * * * public method * * * * * * * */
	
	glUniform : function( field, shader )
	{
		switch( field )
		{
			case SmitearWebGL.ShaderUniform.lightColor:
				this.context.gl.uniform3fv( shader.uniforms.uLightColor.location, new Float32Array( this.baseColor.flatten3v() ) );
				break;
				
			case SmitearWebGL.ShaderUniform.lightIntensity:
				this.context.gl.uniform1f( shader.uniforms.uLightIntensity.location, this.intensity );
				break;
				
			case SmitearWebGL.ShaderUniform.lightAttenuation:
				this.context.gl.uniform3f( shader.uniforms.uLightAttenuation.location, this.constantAttenuation, this.linearAttenuation, this.quadraticAttenuation );
				break;
				
			case SmitearWebGL.ShaderUniform.lightSpotExponent:
				this.context.gl.uniform1f( shader.uniforms.uSpotExp.location, this.spotExponent );
				break;
				
			case SmitearWebGL.ShaderUniform.lightSpotOuterCone:
				this.context.gl.uniform1f( shader.uniforms.uSpotOuterCone.location, this._outerCone );
				break;
				
			case SmitearWebGL.ShaderUniform.lightSpotInnerCone:
				this.context.gl.uniform1f( shader.uniforms.uSpotInnerCone.location, this._innerCone );
				break;
				
			case SmitearWebGL.ShaderUniform.lightSpotPMatrix:
				this.context.gl.uniformMatrix4fv( shader.uniforms.uSpotMatrix.location, false, new Float32Array( this._spotPMatrix.flatten() ) );
				break;
				
			case SmitearWebGL.ShaderUniform.lightDirection:
				this.context.gl.uniform3fv( shader.uniforms.uLightDir.location, new Float32Array( this._worldDir.flatten() ) );
				break;
				
			case SmitearWebGL.ShaderUniform.lightPosition:
				this.context.gl.uniform3f( shader.uniforms.uLightPos.location, this._worldViewMatrix.n41, this._worldViewMatrix.n42, this._worldViewMatrix.n43 );
				break;
		}
	}
	,
	getDirectionX : function()
	{
		return this._direction.x;
	}
	,
	setDirectionX : function( value )
	{
		this._direction.x = value;
		this._status.setBit( SmitearWebGL.Objects.Entity.nTransformDirty, true );
	}
	,
	getDirectionY : function()
	{
		return this._direction.y;
	}
	,
	setDirectionY : function( value )
	{
		this._direction.y = value;
		this._status.setBit( SmitearWebGL.Objects.Entity.nTransformDirty, true );
	}
	,
	getDirectionZ : function()
	{
		return this._direction.z;
	}
	,
	setDirectionZ : function( value )
	{
		this._direction.z = value;
		this._status.setBit( SmitearWebGL.Objects.Entity.nTransformDirty, true );
	}
	,
	setOuterCone : function( deg )
	{
		this._spotPMatrix = null;
		this._outerCone = Math.cos( deg * SmitearWebGL.Core.Math.toRADIANS * 0.5 );
	}
	,
	setInnerCone : function( deg )
	{
		this._innerCone = Math.cos( deg * SmitearWebGL.Core.Math.toRADIANS * 0.5 );
	}
	,
	setBaseColor : function( r, g, b, a )
	{
		this.baseColor.r = r;
		this.baseColor.g = g;
		this.baseColor.b = b;
		this.baseColor.a = a;
	}
	,
	getOuterCone : function()
	{
		return this._outerCone * SmitearWebGL.Core.Math.toDEGREES * 2.0;
	}
	,
	getInnerCone : function()
	{
		return this._innerCone * SmitearWebGL.Core.Math.toDEGREES * 2.0;
	}
	,
	getPMatrix : function( far )
	{
		if( ! this._spotPMatrix )
		{
			var _far = far == undefined ? 1000.0 : far;
			SmitearWebGL.Core.Math.Matrix4x4.makePerspectiveFov( this._spotPMatrix, Math.acos( this._outerCone ) / Math.PI * 360.0, 1.0, 0.1, _far );
		}
		return this._spotPMatrix;
	}
	,
	createSpotBuffer : function()
	{
	}
	,
	updateTransform : function()
	{
		this._super();
		
		if ( this.type != SmitearWebGL.Objects.Light.L_POINT && this.isViewDirty() )
		{
			var vx = this._direction.x;
			var vy = this._direction.y;
			var vz = this._direction.z;
		
			this._worldDir.x = vx * this._normalViewMatrix.n11 + vy * this._normalViewMatrix.n21 + vz * this._normalViewMatrix.n31;
			this._worldDir.y = vx * this._normalViewMatrix.n12 + vy * this._normalViewMatrix.n22 + vz * this._normalViewMatrix.n32;
			this._worldDir.z = vx * this._normalViewMatrix.n13 + vy * this._normalViewMatrix.n23 + vz * this._normalViewMatrix.n33;
			
			this._worldDir.normalize();
		}
	}
	,
	_createResource : function( params )
	{
		this._super();

		this.type = SmitearWebGL.Objects.Light.L_POINT;
		this.baseColor = $C( Math.random(), Math.random(), Math.random(), 1.0 );
		this.intensity = 0.8;
		this.constantAttenuation = 1.0;
		this.linearAttenuation = 0.002;
		this.quadraticAttenuation = 0.0008;
		this.spotExponent = 4.0;

		/* * * * * * * * private property * * * * * * * */
		this._displayType = SmitearWebGL.Objects.Entity.DisplayType.LIGHT;
		this._outerCone = 0.6129;
		this._innerCone = 0.7524;
		this._spotPMatrix = null;

		this._direction = $V3( 0.0, 0.0, -1.0 );
		this._worldDir = $V3();
	}
	,
	_destroyResource : function()
	{
		this._super();
		
		this.baseColor = null;
		this._spotPMatrix = null;
		this._direction = null;
		this._worldDir = null;
	}
}
);

SmitearWebGL.Objects.Light.L_POINT = 1;
SmitearWebGL.Objects.Light.L_DIR = 2;
SmitearWebGL.Objects.Light.L_SPOT = 3;